import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;

public class ChatChannel implements Runnable {
    private Socket socket;           // 客户端连接通道
    private ObjectInputStream ois;   // 接收客户端消息的输入流
    private String name;             // 客户端用户名
    static Map<String, ObjectOutputStream> allMap = new HashMap<>(); // 在线客户端输出流列表

    public ChatChannel(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            // 初始化：接收用户名、发送欢迎消息、注册到在线列表
            recvNameAndEchoHello();
            
            // 消息循环：持续处理客户端发送的消息
            while (true) {
                String msg = (String) ois.readObject();
                
                // 私聊逻辑：消息以@开头，格式为@目标用户#消息内容
                if (msg.indexOf('@') == 0) {
                    int end = msg.indexOf('#');
                    String secretName = msg.substring(1, end); // 提取目标用户名
                    String secretMsg = msg.substring(end + 1);  // 提取消息内容
                    sendSecretMsg(secretName, secretMsg); // 调用私聊方法
                } else {
                    // 群聊逻辑：非私聊消息广播给所有客户端
                    System.out.println(name + "说：" + msg);
                    sendToAll(name + "说：" + msg);
                }
            }
        } catch (IOException e) { // 捕获IO异常（如客户端断开连接）
            allMap.remove(name); // 从在线列表移除当前用户
            System.out.println(name + "退出聊天室"); // 服务端日志提示
            
            try {
                // 广播系统消息告知其他客户端
                sendToAll("系统消息：" + name + "退出聊天室");
            } catch (IOException ex) { // 处理广播时可能出现的异常
                ex.printStackTrace();
            }
            e.printStackTrace(); // 打印原始异常堆栈
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    }

    // 客户端初始化：接收用户名并注册输出流
    private void recvNameAndEchoHello() throws IOException, ClassNotFoundException {
        ois = new ObjectInputStream(socket.getInputStream());
        name = (String) ois.readObject(); // 读取客户端发送的用户名
        
        ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
        oos.writeObject(name + "，您好!欢迎您进入聊天室"); // 发送欢迎消息
        oos.flush();
        allMap.put(name, oos); // 将当前客户端输出流存入在线列表
    }

    // 群聊广播方法：遍历所有在线客户端输出流发送消息
    private void sendToAll(String msg) throws IOException {
        for (ObjectOutputStream oos : allMap.values()) {
            oos.writeObject(msg);
            oos.flush(); // 立即发送，避免缓冲区滞留
        }
    }

    // 私聊方法：根据用户名获取目标客户端输出流并发送消息
    private void sendSecretMsg(String secretName, String msg) throws IOException {
        ObjectOutputStream secretOOS = allMap.get(secretName);
        System.out.println(name + "悄悄地对" + secretName + "说: " + msg); // 服务端日志
        secretOOS.writeObject(name + "悄悄地对您说: " + msg); // 发送私聊消息
        secretOOS.flush();
    }
}